package descentFly
{
	import UIAway.uif_view;
	
	import UIFree.ObjectEvent;
	
	import UIUtils.uif_util;
	
	import descentFly.app.df_events;
	import descentFly.app.df_locale;
	import descentFly.chips.df_chip;
	import descentFly.controller.FlyController;
	import descentFly.controller.df_userController;
	import descentFly.controller.myFlyController;
	import descentFly.sound.df_soundManager;
	import descentFly.weaponts.IBullet;
	
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	import org.osmf.events.TimeEvent;
	
	public class df_space extends df_optionsObject {
		public static const SETMYCHIP		: String = 'SETMYCHIP';
		public static const CHECKBULLETHIT	: String = 'CHECKBULLETHIT';
		public static const CHANGELEVEL		: String = 'CHANGELEVEL';
		public static const SETPLAYER		: String = 'SETPLAYER';
		public static const CHANGEDISABLESCENE	: String = 'CHANGEDISABLESCENE';
		public static const RENDER			: String = 'RENDER';
		
		public static var NORMAL_CYCLE_TIME	: uint = 40;
		
		private var _scene			: Object;
		private var _objects		: Array;
		private var _updateTimer	: Timer;
		private var _app			: Sprite;
		private var _myChip			: df_chip;
		private var _player			: df_player;
		private var _levels			: Array;
		private var _levelID		: int;
		
		protected var _cycleTime	: uint;
		
		public function df_space(a_app: Sprite, a_player: df_player, a_options: Object) {
			super(a_options);
			_cycleTime	= NORMAL_CYCLE_TIME;
			_app 		= a_app;
			_levelID	= -1;
			setPlayer(a_player);
			if (app.stage) initialize();
			else app.addEventListener(Event.ADDED_TO_STAGE, doAddToStage);
		}
		
		public function setPlayer(a_player: df_player): void {
			if (_player != a_player) {
				if (_player) {
					_player.setSpace(null);
					removeEventsPlayer();
				}
				_player 	= a_player;
				if (_player) {
					_player.setSpace(this);
					listenEventsPlayer();
				}
				dispatchEvent(new Event(SETPLAYER));
			}
		}
		
		protected function removeEventsPlayer(): void {
			_player.removeEventListener(df_optionsObject.SETOPTIONS, doPlayerUpdate);
		}
		
		protected function listenEventsPlayer(): void {
			_player.addEventListener(df_optionsObject.SETOPTIONS, doPlayerUpdate);
		}
		
		protected function doPlayerUpdate(e: Event): void {
			if (_player.level != levelID) levelID = _player.level;
		}
		
		override public function dispose():void {
			if (_player) removeEventsPlayer();
			super.dispose();
		}
		
		public function get plockSupport(): Boolean {
			return options.plockSupport;
		}
		
		public function get levels(): Array {
			return _levels;
		}
		
		public function set levels(a_levels: Array): void {
			_levels = a_levels;
		}
								   
		public function get levelID(): int {
			return _levelID;
		}
		
		public function set levelID(a_id: int): void {
			if (_levels && (a_id != _levelID)) {
				setLevelIndex(levelIndexFromID(a_id));
			}
		}
		
		protected function nextLevel(): void {
			var index: int = levelIndexFromID(_levelID);
			setLevelIndex((index + 1) % _levels.length);
		}
		
		public function levelIndexFromID(id: int): int {
			for (var i: int=0; i<_levels.length; i++) {
				if (_levels[i].id == id) 
					return i;
			}
			return -1;
		}
		
		public function setLevelIndex(levelIndex: int): void {
			if (_levels && (levelIndex > -1) && (_levels.length > levelIndex)) {
				loadScene(_levels[levelIndex]);
			}
		}
		
		public function get myChip(): df_chip {
			return _myChip;
		}
		
		public function get player(): df_player {
			return _player;
		}
		
		public function addObject(a_chip: df_chip): df_chip {
			_objects.push(a_chip);
			return a_chip;
		}
		
		public function get monsterCount(): Number {
			return 0;
		}
		
		public function removeObject(a_chip: df_chip): void {
			var index: int = _objects.indexOf(a_chip);
			if (index > -1) _objects.splice(index, 1);
		}
		
		protected function loadScene(a_scene: Object): void {
			if (player.accessLevel(a_scene)) {
				beginLoadScene(uif_util.clone(a_scene));
			} else dispatchEvent(new ObjectEvent(df_events.ALERT, df_locale.NOACCESSLEVEL));
		}
		
		public function get app(): Sprite {
			return _app;
		}
		
		public function get scene(): Object {
			return _scene;
		}
		
/*		public function _actionFire(e_set: Boolean): void {
			if (myChip) myChip.fire(e_set);
		}*/
//------------------------PROTECTED 
		
		protected function initialize(): void {
			chipsInitialize();
			
			_updateTimer = new Timer(options.fps);
			_updateTimer.addEventListener(TimerEvent.TIMER, doRender);
		}
		
		override protected function listenEvents():void {
			addEventListener(df_events.LEVELPASSED, doLevelPassed);
			addEventListener(df_events.NEXTLEVEL, doNextLevel);
		}
		
		override protected function removeEvents():void {
			removeEventListener(df_events.LEVELPASSED, doLevelPassed);
			removeEventListener(df_events.NEXTLEVEL, doNextLevel);
		}
		
		protected function doLevelPassed(e: Event): void {
			if (player.options.maxLevel <= levelID)
				player.options.maxLevel = levelID + 1;
			nextLevel();
		}
		
		private function doNextLevel(e: Event): void {
			nextLevel();
		}
		
		protected function initEnv(initInfo: Object): void {
			soundEnvStart();
		}
		
		protected function soundEnvStart(): void {
			if (scene.Enviroment.sound)
				df_soundManager.playSound(scene.Enviroment.sound)
		}
		
		protected function removeEnv(): void {
			if (scene.Enviroment.sound) 
				df_soundManager.stopSound(scene.Enviroment.sound)
		}
		
		protected function doRender(e: Event): void {
			dispatchEvent(new Event(RENDER));
		}
		
		protected function chipsInitialize(): void {
			_objects = new Array();
		}
		
		public function setMyCurrentChip(a_chip: df_chip): void {
			if (_myChip) {
//				_myChip.removeEventListener(df_chip.UPDATECHIP, doUpdateMyChip);
				_myChip.removeEventListener(df_chip.BULLETHIT, onMyChipBulletHit);
				_myChip.removeEventListener(df_spaceObject.DISPOSE, doMyChipDispose);
			}
			_myChip = a_chip;
			if (_myChip) {
//				_myChip.addEventListener(df_chip.UPDATECHIP, doUpdateMyChip);
				_myChip.addEventListener(df_chip.BULLETHIT, onMyChipBulletHit);
				_myChip.addEventListener(df_spaceObject.DISPOSE, doMyChipDispose);
				
				//_myChip.deathless = true; // Бессмертие ON
				if (player && (player.live > 0)) _myChip.setLive(player.live / 100);
			}
			dispatchEvent(new ObjectEvent(SETMYCHIP, _myChip));
		}
		
		private function onMyChipBulletHit(e: ObjectEvent): void {
			doMyChipBulletHit(e.object);
		}
		
		protected function doMyChipBulletHit(hitInfo: Object): void {
		}
		
		protected function doMyChipDispose(e: Event): void {
			setMyCurrentChip(null);
		}
		
		public function forEach(func: Function, objectClass: Class = null): Object {
			var i:int = 0;
			while (i < _objects.length) {
				var chip: Object = _objects[i];
				if (!objectClass || (chip is objectClass)) {
					var result: Object = func(chip, i);
					if (result) return result;
				}
				i++;
			}
			return null;
		}
		
		public function getObjectCount(objectClass: Class=null): int {
			if (!objectClass || (objectClass is df_chip)) 
				return _objects.length;
			
			var count: int;
			forEach(function(object: Object, i: int): void {
				count++;
			}, objectClass)
			return count;
		}
	
/*		
		private function doCheckBulletHit(e: ObjectEvent): void {
			checkBulletHit(e.object as IBullet);
		}
		
		private function checkBulletHit(bullet: IBullet): void {
			forEach(function(chip: df_chip, i: int): void {
				if (bullet.chip != chip) {
					chip.checkHit(bullet);
				}
			});
		}*/
		
		protected function beginLoadScene(a_scene: Object): void {
			if (_scene) clear();
			_scene = a_scene;
			_levelID = _scene.id; 
			
			for (var prop: String in _scene) {
				if (prop.substr(0, 1) <= 'Z') // Только у которых первая буква заглавная
					loadElement(prop, _scene[prop]);
			}
			afterLoadScene();
			dispatchEvent(new ObjectEvent(CHANGELEVEL, _scene));
		}

		protected function afterLoadScene(): void {
			_updateTimer.start();
		}
		
		protected function removeObjects(): void {
			while (_objects.length > 0) {
				(_objects[0] as df_chip).dispose();
			}
		}
		
		public function get disableScene(): Boolean {
			return false;
		}
		
		protected function setDisableScene(set: Boolean): void {
			dispatchEvent(new ObjectEvent(CHANGEDISABLESCENE, set));
		}
		
		public function set disableScene(set: Boolean): void {
			if (set != disableScene) setDisableScene(set);
		}
		
		public function clear(): void {
			removeEnv();
			removeObjects();
			dispatchEvent(new Event(Event.CLEAR));
		}
		
		public function get cycleTime(): uint {
			return _cycleTime;
		}
//--------------------------------------------PRIVATES		
		private function doAddToStage(e: Event): void {
			app.removeEventListener(Event.ADDED_TO_STAGE, doAddToStage);
			initialize();
		}
		
		private function loadElement(elemName: String, elem: Object): void {
			this['set' + elemName](elem);
		}
		
/*		private function doActionBegin(e: ObjectEvent): void {
			changeActionState(e.object as String, true);
		}
		
		private function doActionStop(e: ObjectEvent): void {
			changeActionState(e.object as String, false);
		}
		
		private function changeActionState(actionName: String, a_state: Boolean): void {
			var methodName: String = '_action' + actionName;
			if (hasOwnProperty(methodName)) this[methodName](a_state);
		}*/
	}
}